package fra;

import java.util.Iterator;

public class Matrix2<E> implements Iterable<E> {
	Object objArr[][];//内部矩阵
	final Size size;//大小
	String name;//矩阵名称
	
	/**构造函数*****************************************************/
	public Matrix2(){
		this("NoName");
	}
	public Matrix2(String name) {
		objArr=new Object[0][0];
		size=new Size(0);
		this.name=name;
	}
	public Matrix2(String name,Size size) {
		objArr=new Object[size.row][size.col];
		this.size=size;
		this.name=name;
	}
	public Matrix2(Size size) {
		this("NoName",size);
	}
	public Matrix2(String name,int row,int col) {
		this(name,new Size(row,col));
	}
	public Matrix2(int row,int col) {
		this(new Size(row,col));
	}
	public Matrix2(String name,int len) {
		this(name,new Size(len));
	}
	public Matrix2(int len) {
		this(new Size(len));
	}
	public Matrix2(String name,E[][] objArr,Size size){
		this(name,size);
		for (int i = 0; i <size.row; i++) {
			for (int j = 0; j < size.col; j++) {
				this.objArr[i][j]=objArr[i][j];
			}
		}
	}	
	public Matrix2(E[][] objArr,Size size){
		this("NoName",objArr,size);
	}
	public Matrix2(String name,E[][] objArr,int row,int col){
		this(name,objArr,new Size(row,col));
	}
	public Matrix2(E[][] objArr,int row,int col){
		this("NoName",objArr,new Size(row,col));
	}
	public Matrix2(String name,E[][] objArr,int len){
		this(name,objArr,new Size(len));
	}
	public Matrix2(E[][] objArr,int len){
		this("NoName",objArr,new Size(len));
	}
	public Matrix2(String name,E[] objArr,boolean isDefault){
		this(name,isDefault?new Size(1,objArr.length):new Size(objArr.length,1));
		if(isDefault){
			for (int i = 0; i < objArr.length; i++) {
				this.objArr[0][i]=objArr[i];
			}
		}else{
			for (int i = 0; i < objArr.length; i++) {
				this.objArr[i][0]=objArr[i];
			}
		}		
	}
	public Matrix2(E[] objArr,boolean isDefault){
		this("NoName",objArr,isDefault);
	}
	public Matrix2(String name,E[] objArr){
		this(name,objArr,true);
	}
	public Matrix2(E[] objArr){
		this("NoName",objArr,true);
	}
	public Matrix2(Matrix2<E> m){
		this(m.getName(),m.size);
		for (int i = 0; i <size.row; i++) {
			for (int j = 0; j < size.col; j++) {
				this.objArr[i][j]=m.objArr[i][j];
			}
		}
	}
	
	/**重写函数**************************************************/
	@Override
	public String toString() {
		StringBuilder sb=new StringBuilder();
		sb.append(this.name);
		if(isEmpty()){
			sb.append(" = [\t]\n");
		}else{
			sb.append(" = \n[\t");
			for (int i = 0; i < getRow(); i++) {
				if(i>0)
					sb.append("\n\t");
				for (int j = 0; j < getCol(); j++) {
					sb.append(objArr[i][j]);
					sb.append("\t");
				}
			}		
			sb.append("]\n");
		}
		return sb.toString();
	}
	@SuppressWarnings("rawtypes")
	@Override
	public boolean equals(Object obj) {
		if(obj==null)return false;
		if(!(obj instanceof Matrix2))return false;
		Matrix2 m=(Matrix2)obj;
		if(!m.size.equals(size))return false;
		for (int i = 0; i < getRow(); i++) {
			for (int j = 0; j < getCol(); j++) {
				if(!m.get(i, j).equals(get(i,j)))return false;
			}
		}
		return true;
	}
	/**功能*****************************************************/
	/**
	 * 克隆矩阵
	 */
	public Matrix2<E> clone(){
		return new Matrix2<E>(this);
	}
	/**
	 * 矩阵序列化
	 * @return
	 */
	public Object[] get(){
		Object objs[]=new Object[size.col*size.row];
		for (int i = 0; i < objs.length; i++) {
			objs[i]=get(i+1);
		}
		return objs;
	}
	/**
	 * 转置
	 * @return
	 */
	public Matrix2<E> turn(){
		Matrix2<E> m=new Matrix2<E>(getName()+"_turn", size.col,size.row);
		for (int i = 0; i < size.row; i++) {
			for (int j = 0; j < size.col; j++) {
				m.objArr[j][i]=objArr[i][j];
			}
		}
		return m;
	}
	/**
	 * 判断是否为空矩阵
	 * @return
	 */
	public boolean isEmpty(){
		return size.row*size.col==0;
	}
	/**
	 * 获取多行数据
	 * @param rows
	 * @return
	 */
	public Matrix2<E> getRows(int ... rows){
		if(rows.length==0)return new Matrix2<E>();
		for (int i = 0; i < rows.length; i++) {
			if(rows[i]<0&&rows[i]>=getRow()){
				throw new ArrayIndexOutOfBoundsException("数组行号越界");
			}
		}
		Matrix2<E> m=new Matrix2<E>(rows.length,getCol());
		for (int i = 0; i < rows.length; i++) {
			for (int j = 0; j < getCol(); j++) {
				m.set(i, j, get(rows[i], j));
			}
		}
		return m;
	}
	/**
	 * 获取多列数据
	 * @param cols
	 * @return
	 */
	public Matrix2<E> getCols(int ... cols){
		if(cols.length==0)return new Matrix2<E>();
		for (int i = 0; i < cols.length; i++) {
			if(cols[i]<0&&cols[i]>=getCol()){
				throw new ArrayIndexOutOfBoundsException("数组行号越界");
			}
		}
		Matrix2<E> m=new Matrix2<E>(getRow(),cols.length);
		for (int i = 0; i < getRow(); i++) {
			for (int j = 0; j < cols.length; j++) {
				m.set(i, j, get(i, cols[j]));
			}
		}
		return m;
	}
	/**
	 * 获取数据块
	 * @param rows
	 * @param cols
	 * @return
	 */
	public Matrix2<E> get(int rows[],int cols[]){
		if(cols.length==0||rows.length==0)return new Matrix2<E>();
		for (int i = 0; i < rows.length; i++) {
			if(rows[i]<0&&rows[i]>=getRow()){
				throw new ArrayIndexOutOfBoundsException("数组行号越界");
			}
		}
		for (int i = 0; i < cols.length; i++) {
			if(cols[i]<0&&cols[i]>=getCol()){
				throw new ArrayIndexOutOfBoundsException("数组行号越界");
			}
		}
		
		Matrix2<E> m=new Matrix2<E>(rows.length,cols.length);
		for (int i = 0; i < rows.length; i++) {
			for (int j = 0; j < cols.length; j++) {
				m.set(i, j, get(rows[i], cols[j]));
			}
		}
		return m;
	}
	/**属性*****************************************************/
	/**
	 * 获取列
	 * @return
	 */
	public int getCol() {
		return size.col;
	}
	/**
	 * 获取行
	 * @return
	 */
	public int getRow() {
		return size.row;
	}
	/**
	 * 获取矩阵大小
	 * @return
	 */
	public Size gatSize(){
		return size;
	}
	/**
	 * 获取数组名称
	 * @return
	 */
	public String getName() {
		return name;
	}
	
	@SuppressWarnings("unchecked")
	public E get(int i,int j){
		if(i>=size.row||j>=size.col){
			throw new ArrayIndexOutOfBoundsException("数组越界");
		}
		if(objArr[i][j]==null)return null;
		return (E)objArr[i][j];
	}
	@SuppressWarnings("unchecked")
	public E get(int index){
		if(index<1||index>getRow()*getCol()){
			throw new ArrayIndexOutOfBoundsException("数组越界");
		}
		index-=1;
		if(objArr[index%getRow()][index/getRow()]==null)return null;
		return (E)objArr[index%getRow()][index/getRow()];
	}
	/*set方法*/
	/**
	 * 设置数组的值
	 * @param i
	 * @param j
	 * @param obj
	 */
	public void set(int i,int j,E obj){
		if(i>=size.row||j>=size.col){
			throw new ArrayIndexOutOfBoundsException("数组越界");
		}
		objArr[i][j]=obj;
	}
	public void set(int index,E obj){
		if(index<1||index>getRow()*getCol()){
			throw new ArrayIndexOutOfBoundsException("数组越界");
		}
		index-=1;
		objArr[index%getRow()][index/getRow()]=obj;
	}
	public void set(E obj){
		for (int i = 0; i < getRow(); i++) {
			for (int j = 0; j < getCol(); j++) {
				objArr[i][j]=obj;
			}
		}
	}
	/**
	 * 设置数组名称
	 * @param name
	 */
	public void setName(String name) {
		if(name==null||name.trim().length()==0)return;
		this.name = name;
	}
	@Override
	public Iterator<E> iterator() {
		return new Iterator<E>() {
			int index=1;
			@Override
			public boolean hasNext() {
				return index<=getCol()*getRow();
			}

			@Override
			public E next() {
				return get(index++);
			}
			@Override
			public void remove() {
				throw new NoSuchFieldError("未启用该函数");
			}
		};
	}
	public static void main(String[] args) {
		int arr[]={1,2,3,4};
		Matrix2<Integer> m=new Matrix2<Integer>("arr",1,4);
		for (int i = 0; i < arr.length; i++) {
			m.set(i+1,arr[i]);
		}
		//System.out.println(m.getCols(0,2));
		for (Integer integer : m) {
			System.out.println(integer);
		}
	}
}
